/**
* Class Name: ItemSearchController
* Author: Accenture
* Date: 13-Jun-2011
* Requirement/Project Name: iFulfill
* Requirement/Project Description: Controller for FI search VF page.
**/


public class ItemSearchController
{
    public boolean selectFormMyQueue {get;set;}
    public boolean renderClaim {get;set;}
    public String escalatedCheckBox{get;set;}   
    public boolean renderChangeOwner {get;set;}
    public boolean noSearchResults{get;set;}       
    public boolean searchResults{get;set;}   
    public boolean enableMyqueueName {get;set;}
    public boolean errorFlag {get;set;}

    private boolean nxtSearch;
    private boolean prevSearch; 
    
    public String sortField {get; set;}
    public String previousSortField {get; set;}
    public String  selectedRegion {get;set;}  
    public String  selectedTransactionType {get;set;} 
    public String  listedName {get;set;}
    public String  productCode {get;set;}
    public String  itemId {get;set;}
    public String  ypcHeadingCode     {get;set;}
    public String  listingPhoneNumber{get;set;}
    public String  udac {get;set;} 
    public String  customerID {get;set;}  
    public String  currentFunctionName {get;set;}  
    public String  featureCode {get;set;}
    public String  productFamilyName{get;set;}  
    public String currentTaskName {get;set;}  
    public String productIssue {get;set;}
    public String accountName {get;set;} 
    public String status {get;set;}  
    public String OwnerName {get;set;}
    public String filterViews {get;set;}
    public String myQueueName {get;set;}
    public String changeOwnerQueue {get;set;}
    private String loggedUserName;
    private String maxId;
    
    
    private Id usrId ;
    
    public  List<selectOption> stepOption {get;set;}
    private List<Fullfilment_Item__c> fullFilmentItemList = new List<Fullfilment_Item__c>();
    private List<FullfilmentWrapper> displayedWrapperList = new List<FullfilmentWrapper>();
    
    private set<id> qSetIds = new set<id>();

    // Holds FI selected  the user 
    private Map<ID,Fullfilment_Item__c> selectedMap = new Map<ID,Fullfilment_Item__c>();
    
    public final Integer pageSize {get;set;}
    private integer searchCount; 
    public Integer pageNo {get;set;}
    
    public Fullfilment_Item__c  FulfillItem{get;set;} 
   
    // FI wrapper class
    class FullfilmentWrapper
    {
        public Fullfilment_Item__c item{get;set;}
        public boolean selectBox{get;set;}
        Public FullfilmentWrapper(Fullfilment_Item__c I, Boolean checkBox)
        {
            item = I;
            selectBox = checkBox;
        }
    }
    
    /*
     *  Constructor 
     **/
        
    public ItemSearchController()
    {
        stepOption = new  List<selectOption>();
        stepOption.add(new selectOption('', IfullfillTextConstant.PICKLIST_NONE_TXT)); 
        usrId =  Userinfo.getUserId(); 
        loggedUserName = UserInfo.getName(); 
        searchResults = false;
        noSearchResults = false;  
        pageNo = 0;
        pageSize  = 20;     
        enableMyqueueName = false;
        selectFormMyQueue = false; 
        renderChangeOwner  = false;
        renderClaim = false;
        escalatedCheckBox = '';
        myQueueName = IfullfillTextConstant.ALL_TXT;
        FulfillItem = new Fullfilment_Item__c();
        searchCount = 0;
        maxId = '';
        nxtSearch = false;
        prevSearch = false;
        FullfilmentWrapper fiWrapper  = new FullfilmentWrapper(null, false);
        renderChangeOwner  = initializeChangeOwner();
    }
    
    /*
     *  Perform the search based on the input provided by the user.
     *
     **/
    public pageReference doSearch()
    {   
    
        boolean esclated1 = false;
        boolean esclated2 = false;
        
        String groupID = null;
        String qString;
        List <GroupMember> gMemberList = new list<GroupMember>();
               renderClaim  = (filterViews != null && filterViews.equalsIgnoreCase(IfullfillTextConstant.MY_QUEUE_ITEMS_TXT)) ? true : false; 
      
       // Check  this is a  new search or user has clicked on next/preveious link on the pagination
       
        if(!(nxtSearch ||prevSearch ))
        {
            listingPhoneNumber = '';
            searchCount =  0;
            pageNo = 0;
            maxId = '';
            displayedWrapperList .clear();
            fullFilmentItemList.clear();
            selectedMap.clear();
        }    
        listingPhoneNumber = FulfillItem.Main_Listing_Phone_Number__c;
        gMemberList = [select id, GroupId from GroupMember where UserOrGroupId =: usrId ];

        for(GroupMember gm :gMemberList )
        {
        
           if(groupID   == null)
           {
               groupID  = ' \''+ gm.groupid + '\'';
           }
           else
           {
           groupID  = groupID + ', \''+ gm.groupid + '\'';
           }
        
            groupID  = groupID + ', \''+ gm.groupid + '\'';

        } 

       // Check if user  has selected the Escalted list option
        if(escalatedCheckBox != null && escalatedCheckBox.trim() != '')
        {
           // Check if user has selected NON ESCALATED pick list value 
           if(escalatedCheckBox == IfullfillTextConstant.NON_ESCALATED_TXT)
           {
               esclated1 = false;
               esclated2 = false;
           }
           else
           {      
               esclated1 = true;
               esclated2 = true;
           }           
        }
        else
        {
            esclated1 = true;
            esclated2 = false;
        }

        // Check the user has clicked next link on the pagination
        if(nxtSearch)   
            qString = 'select Owner_Reporting__c,Future_Cancellation__c ,   Main_Listed_Name__c, Current_Step_Start_Date__c , Current_Step_Target_days__c , YPC_Heading_Code__c ,Listed_Name__c,Main_Listing_Phone_Number__c, Account__r.Name,  Customer_ID__c, id,Current_Task_Indicator__c,Current_Step_Aging__c,Item_Id__c,ownerId,name,owner.alias,Product_Code__c,Product_issue__c,current_stage__r.name ,current_step__r.name,UDAC__c,Feature_Code__c, Transaction_Type__c,Region__c,Status__c,Escalated__c from Fullfilment_Item__c  where name > \'' + maxId + '\' and  (Escalated__c =' + esclated1 + ' or Escalated__c = ' +esclated2 +' )'  ;   
        // Check the user has clicked previous link on the pagination    
        else if(prevSearch) 
             qString = 'select  Owner_Reporting__c,Future_Cancellation__c , Main_Listed_Name__c, Current_Step_Start_Date__c , Current_Step_Target_days__c,  YPC_Heading_Code__c ,Listed_Name__c,Main_Listing_Phone_Number__c, Account__r.Name,  Customer_ID__c, id,Current_Task_Indicator__c,Current_Step_Aging__c,Item_Id__c,ownerId,name,owner.alias,Product_Code__c,Product_issue__c,current_stage__r.name ,current_step__r.name,UDAC__c,Feature_Code__c, Transaction_Type__c,Region__c,Status__c,Escalated__c from Fullfilment_Item__c  where name < \'' + maxId + '\' and (Escalated__c =' + esclated1 + ' or Escalated__c = ' +esclated2 +' )'  ;   
        else 
        //fresh search.
         qString = 'select  Owner_Reporting__c, Future_Cancellation__c ,    Main_Listed_Name__c, Current_Step_Start_Date__c , Current_Step_Target_days__c , YPC_Heading_Code__c ,Listed_Name__c,Main_Listing_Phone_Number__c, Account__r.Name,  Customer_ID__c, id,Current_Task_Indicator__c,Current_Step_Aging__c,Item_Id__c,ownerId,name,owner.alias,Product_Code__c,Product_issue__c,current_stage__r.name,current_step__r.name,UDAC__c,Feature_Code__c, Transaction_Type__c,Region__c,Status__c,Escalated__c from Fullfilment_Item__c where (Escalated__c =' + esclated1 + ' or Escalated__c = ' +esclated2 +' )' ;
        
        String qString1 = 'select count() from Fullfilment_Item__c where (Escalated__c =' + esclated1 + ' or Escalated__c = ' +esclated2 +' )'  ;  
       
        
        // Check all the field or null if not null add the value as part of the query
        if(customerID!= null && customerID.trim() != '')
        {
            qString = qString + ' and   Customer_ID__c like \'' + customerID.trim() + '%\'';        
            qString1 = qString1 + ' and   Customer_ID__c like \'' + customerID.trim() + '%\'';              
        }

        if(accountName!= null && accountName.trim() != '')
        {
            qString = qString + ' and  Account__r.Name like \'' +String.escapeSingleQuotes(accountName.trim()) + '%\'';  
            qString1 = qString1 + ' and  Account__r.Name like \'' + String.escapeSingleQuotes(accountName.trim())+ '%\'';              
        }
         
       
        if(listingPhoneNumber  != null &&listingPhoneNumber.trim() != '')
        {  
            qString = qString + ' and Main_Listing_Phone_Number__c like \'' +listingPhoneNumber.trim() + '%\'';                           
            qString1 = qString1 + ' and Main_Listing_Phone_Number__c like \'' +listingPhoneNumber.trim() + '%\'';              
        }
        if(listedName  != null && listedName.trim() != '')
        {  
            qString = qString + ' and Main_Listed_Name__c like \'' + String.escapeSingleQuotes(listedName.trim())  + '%\'';   
            qString1 = qString1 + ' and Main_Listed_Name__c like \'' + String.escapeSingleQuotes(listedName.trim())  + '%\'';                                       
        }
        
        if(ypcHeadingCode     != null && ypcHeadingCode.trim()      != '')
        {  
            qString = qString + ' and   YPC_Heading_Code__c like \'' + ypcHeadingCode.trim()      + '%\'';                           
            qString1 = qString1 + ' and     YPC_Heading_Code__c  like \'' + ypcHeadingCode.trim()      + '%\'';             
        }
           
       // qString = qString + ' Product_Family__c =\'' + FulfillItem.Product_Family__c + '\'';       
        if(currentFunctionName != null && currentFunctionName!= '')
        {
            qString = qString + ' and Current_Function_Name__c = \'' + currentFunctionName + '\''; 
            qString1 = qString1 + ' and Current_Function_Name__c = \'' + currentFunctionName + '\'';                    
        }
        
        if(currentTaskName != null && currentTaskName!= '')
        {  
            qString = qString + ' and Current_Task_Name__c =\'' + currentTaskName + '\''; 
            qString1 = qString1 + ' and Current_Task_Name__c =\'' + currentTaskName + '\'';                                       
        }
        
        if(productFamilyName!= null && productFamilyName!= '')
        {  
            qString = qString + ' and Product_Family__c =\'' + productFamilyName+ '\''; 
            qString1 = qString1 + ' and Product_Family__c =\'' + productFamilyName+ '\'';                                       
        }
               
        if(status != null && status!= '' && !(filterViews != null && filterViews!= '' && filterViews.equalsIgnoreCase(IfullfillTextConstant.MY_QUEUE_ITEMS_TXT)))
        {  
            qString = qString + ' and Status__c =\'' + status + '\'';                           
            qString1 = qString1 + ' and Status__c =\'' + status + '\'';                       
        }
        
        if(itemId  != null && itemId.trim()  != '')
        {  
            qString = qString + ' and Item_Id__c like \'' + itemId.trim()   + '%\'';                           
            qString1 = qString1 + ' and Item_Id__c like \'' + itemId.trim()   + '%\'';                  
        }
       
         if(filterViews != null && filterViews!= '' && filterViews.equalsIgnoreCase(IfullfillTextConstant.MY_ITEMS_TXT)){
         
             qString = qString + ' and Owner.Name like \'%' + loggedUserName + '%\'';
             qString1 = qString1 + ' and Owner.Name like \'%' + loggedUserName + '%\'';             
         }
         else if(filterViews != null && filterViews!= '' && filterViews.equalsIgnoreCase(IfullfillTextConstant.MY_QUEUE_ITEMS_TXT) && myQueueName.equalsIgnoreCase(IfullfillTextConstant.ALL_TXT) )
         {
         
             qString = qString + ' and Owner.Id in ( '+ groupID    +' ) and Status__c=\''+IfullfillTextConstant.FI_WORKFLOW_OPEN_STATUS+ '\'' ;             
             qString1 = qString1 + ' and Owner.Id in ( '+ groupID    +' ) and Status__c=\''+IfullfillTextConstant.FI_WORKFLOW_OPEN_STATUS+ '\'' ;                                                                             
         }
         else if(filterViews != null && filterViews!= '' && filterViews.equalsIgnoreCase(IfullfillTextConstant.MY_QUEUE_ITEMS_TXT)  )
         {
         
              qString = qString + ' and Owner.Id in ( \''+ myQueueName +'\' ) and Status__c=\''+IfullfillTextConstant.FI_WORKFLOW_OPEN_STATUS+ '\'' ;
              qString1 = qString1 + ' and Owner.Id in ( \''+ myQueueName +'\' ) and Status__c=\''+IfullfillTextConstant.FI_WORKFLOW_OPEN_STATUS+ '\'' ;                                                                               
                                                                                             
         }
       
         else{  
                
             if(OwnerName!= null && OwnerName.trim()!= '')
             {
                qString = qString + ' and Owner.Name like \'%' + OwnerName.trim() + '%\'';
                qString1 = qString1 + ' and Owner.Name like \'%' + OwnerName.trim() + '%\'';
                
             }
         }               
        if(productCode  != null && productCode.trim() != '')
        {  
            qString = qString + ' and Product_Code__c like \'' + productCode.trim()  + '%\'';
            qString1 = qString1 + ' and Product_Code__c like \'' + productCode.trim()  + '%\'';                           
        }
       
        if(productIssue != null && productIssue.trim() != '')
        {  
            qString = qString + ' and Product_issue__c like \'' + productIssue.trim()  + '%\'';
            qString1 = qString1 + ' and Product_issue__c like \'' + productIssue.trim()  + '%\'';                           
                                       
        }
       
     
        if(udac  != null && udac.trim() != '')
        {
             qString = qString + ' and UDAC__c LIKE \'' + udac.trim()  + '%\'';
             qString1 = qString1 + ' and UDAC__c LIKE \'' + udac.trim()  + '%\'';
        }
        if(featureCode != null && featureCode.trim() != '')
        {
            qString1 = qString1 + ' and Feature_Code__c LIKE\'' + featureCode.trim()  + '%\'';
            qString = qString + ' and Feature_Code__c LIKE\'' + featureCode.trim()  + '%\'';
          }
                     
        if(selectedRegion  != null && selectedRegion != '') 
        {
           qString = qString + ' and Region__c =\'' + selectedRegion  + '\'';     
           qString1 = qString1 + ' and Region__c =\'' + selectedRegion  + '\'';
        }                   
        if(selectedTransactionType != null && selectedTransactionType != '') 
        {    
            qString = qString + ' and Transaction_Type__c =\'' + selectedTransactionType + '\'';                        
            qString1 = qString1 + ' and Transaction_Type__c =\'' + selectedTransactionType + '\'';
        }
       
       qString = qString + ' Order by name asc Limit ' +pageSize;
       qString1 = qString1 + ' Limit ' + (Limits.getLimitQueryRows() - 5000);  

      
       Decimal heapPercentage = Limits.getLimitHeapSize() * .75;
       try
       {
           // Check total number records only when fresh search is issued.
           if(!(nxtSearch ||prevSearch ))
           {
               searchCount = Database.countQuery(qString1);
               searchCount = searchCount == null ? 0 :searchCount ;
           }       
           
           // Get the record batch by batch and execute the query

                       
            for (List<Fullfilment_Item__c>  tempList : Database.Query(qString))
            {
                fullFilmentItemList.addAll(tempList );
                
                // Check if heap usage is exceeding the governer limits
                if (Limits.getHeapSize() > heapPercentage ) 
                {
                    break;
                }
             }
        }
        catch(Exception e)
        {
                GeneralConstants.mailAnyExceptionToMe('ItemSearchController','doSearch',e);
                System.debug('Error while fetching the records');
        }
        
        setMaxID();
        // check if query has returned any row.
        if(searchCount > 0  )
        {
            searchResults = true;
            noSearchResults = false;           
        }
        else
        {
             noSearchResults = true;
             searchResults = false;
        }
        
        nxtSearch = false;
        prevSearch = false;
        return Null;
    }
    
   /*
   * Check is there any records displayed for next page.
   *
   **/ 
  public boolean getHasNext()
  {
        integer total = pageNo * pageSize;
        return total + pageSize < searchCount ? true : false;
  }
  /*
   * check user is in first page of the pagination
   *
   **/
  
    public boolean getHasPrevious()
    {
       return pageNo  == 0 ? false : true;
    }
    
  /*
   *  Move to next page if more records are present.
   *
   **/
    public void next()
    {
       nxtSearch = true;
       populatedSelectedRec();
       fullFilmentItemList.clear();
       pageNo++;
       integer total = pageNo * pageSize;
       if(!(total < searchCount ))
       {
          pageNo--;
       }
       doSearch();
    }
  /*
   *  Move to previous page if more records are present.
   *
   **/
    public void prevoius ()
    {      
       prevSearch = true;        
       populatedSelectedRec();
       fullFilmentItemList.clear();
       pageNo--;
       pageNo = Math.max(pageNo,0);
       doSearch();
    }
    
    /*
     * Returns the elements that are displayed on the page.
     *
     **/  
    
    public list<FullfilmentWrapper> getSelectedElements()
    {
          integer maxlimit = pageSize;
          Set<ID> selecteRowId = selectedMap.keySet(); 
                  
           if(fullFilmentItemList.size()  < pageSize)
           {
               maxlimit = fullFilmentItemList.size();
           }
          displayedWrapperList.clear();
           for(integer i=0;i<maxlimit;i++)
           {          
               displayedWrapperList.add(new FullfilmentWrapper(fullFilmentItemList.get(i) , selecteRowId.contains(fullFilmentItemList.get(i).id) ));
           }           
           return displayedWrapperList ;      
    }
       
    /* 
     *  user claim the FI to work on it.
     *
     **/
    public pageReference doClaim()
    {
        errorFlag = false;
        Set<ID> tempID = null;
         List<Fullfilment_Item__c> UpdatefullFilmentItemList = new List<Fullfilment_Item__c>();  
          populatedSelectedRec();  
         String fiName = checkStatus();
        
         tempID  = selectedMap.keySet();
          
          // check if user has selected the FI in live,outed and cancel state    
          if(fiName != null)
          {
                String temp  = 'Cannot claim '+ fiName +' fullfilment item  please deselect the row.';
                ApexPages.Message msg = new ApexPages.Message(ApexPages.Severity.ERROR,temp );
                ApexPages.addMessage(msg);
                return null;
          }
          
          
         for (Id fiID : tempId)
         {
            Fullfilment_Item__C item  = selectedMap.get(fiID);
            if(item != null)
            {
                  Item.ownerId = UsrId;
                  UpdatefullFilmentItemList.add(Item);    
            }
            
         }
         // check if there are any records has to updated.
         if(UpdatefullFilmentItemList.size()>0)
            {
                try
                {
                   // claim the FI and update the FI 
                   Update UpdatefullFilmentItemList;
                   doSearch();
                }
                catch(dmlException e)
                {
                    GeneralConstants.mailAnyExceptionToMe('ItemSearchController','doClaim', e); 
                }
                
             }
        
        else
        {
            // Error message if user has not selected any row
             errorFlag = true;
             ApexPages.Message msg = new ApexPages.Message(ApexPages.Severity.ERROR,IfullfillTextConstant.CLAIM_ERROR_MSG);
             ApexPages.addMessage(msg);
            return null;      
        }
        return null;
     }
    
    public void dummy()
    {
    }    
  /*
   * Return the task associated with the selected function
   *
   **/
   
    public void currentTask()
    {
        System.debug('Invoked');
        List<selectOption> options = new List<selectOption>(); 
        options.add(new selectOption('', IfullfillTextConstant.PICKLIST_NONE_TXT )); 
        
        for (Step_Definition__c stepDef : [ select name from  Step_Definition__c where Stage__r.name = :currentFunctionName   order by name asc])
        {
                options.add(new selectOption(stepDef.Name, stepDef.Name));
        }
        stepOption = options;
   }
  /*
   * Return the function
   *
   **/   
    public List<selectOption> getCurrentFunction()
    {
        List<selectOption> options = new List<selectOption>(); 
        options.add(new selectOption('', IfullfillTextConstant.PICKLIST_NONE_TXT )); 
        for (Stage_Definition__c stagDef : [SELECT Id, Name FROM  Stage_Definition__c  order by name asc]) 
        { 
            options.add(new selectOption(stagDef.Name, stagDef.Name)); 
        }
        return options; 
    }
    /* 
     *   Returns the product Family of FI 
     *
     **/
    public List<SelectOption> getProductFamily()
    {
        List<selectOption> options = new List<selectOption>(); 
        options.add(new selectOption('', IfullfillTextConstant.PICKLIST_NONE_TXT)); 
        Schema.DescribeFieldResult rest =   Fullfilment_Item__c.Product_Family__c.getDescribe();
        for(Schema.PickListEntry FinalsPickVal : rest.getPicklistValues())
        {
            options.add(new SelectOption(FinalsPickVal.getValue(),FinalsPickVal.getLabel()));
        }
        return options;
    } 
    /* 
     *   Return the FI worklow Status
     *
     **/
    public List<SelectOption> getWorkflowStatus()
    {
        List<selectOption> options = new List<selectOption>(); 
        options.add(new selectOption('', IfullfillTextConstant.PICKLIST_NONE_TXT)); 
        Schema.DescribeFieldResult rest =   Fullfilment_Item__c.Status__c.getDescribe();
        for(Schema.PickListEntry FinalsPickVal : rest.getPicklistValues())
        {
            options.add(new SelectOption(FinalsPickVal.getValue(),FinalsPickVal.getLabel()));
        }
        return options;
    }  
    /* 
     *   return the No record fetched.
     *
     **/
    public integer getTotalNoOfRecord()
    {
    
        return searchCount ;
    }    
    
  /*
   * Action associated with the clear button
   *
   **/
    public void clear()
    {
    
        List<selectOption> options = new List<selectOption>(); 
        fullFilmentItemList.clear();
        displayedWrapperList.clear();
        selectedMap.clear();
          
         options.add(new selectOption('', IfullfillTextConstant.PICKLIST_NONE_TXT )); 
         stepOption = options;
          enableMyqueueName = false;
          searchCount =  0;
          pageNo = 0;
          maxId = '';
         escalatedCheckBox = '';
          searchResults = false;

          noSearchResults = false;
        
    }
    
  /*
   * Return the task associated with the selected function
   *
   **/
    public List<SelectOption> getMyqueues()
    {
        String UserID  = UserInfo.getUserId();
        List<selectOption> options = new List<selectOption>(); 
        options.add(new selectOption(IfullfillTextConstant.ALL_TXT, IfullfillTextConstant.ALL_TXT)); 
        options.addAll(getQueues());
      
        return options;
    }
    /*
     * Returns the queue associate with login user 
     *
     **/
    public List<SelectOption> getQueues()
    {
        String UserID  = UserInfo.getUserId();
        List<selectOption> options = new List<selectOption>(); 
        List<Group> groupList =[select id ,name from group where type ='Queue' and id in  (Select  g.GroupId From GroupMember g WHERE userORGroupid = :UserID) order by name asc ];       
        for(Group  obj : groupList )
        {
            options.add(new SelectOption(obj.id, obj.name));
        }
        return options;
    }
    
    
  /*
   * Check My QUEUE_ITEMS is selected in the filter view
   *
   **/
    
    public void enableMyQueue()
    {
        enableMyqueueName = true;
        if(filterViews != null && filterViews.equalsIgnoreCase(IfullfillTextConstant.MY_QUEUE_ITEMS_TXT))
        {
            enableMyqueueName = false;
        }
    }
  /**
   * Change the owner of the selected records
   *
   */
    public Pagereference changeOwner()
    {
          Integer count = 0 ;
          String fiName  = null;
          Pagereference Page = new Pagereference(IfulfillVFPagesName.CHANGE_OWNER_PAGE);   
          Set<ID> selecteRowId = selectedMap.keySet();
           
           populatedSelectedRec();
           // Check the user has selected the row are not 
           if(selecteRowId.size() <= 0 )
           {
                ApexPages.Message msg = new ApexPages.Message(ApexPages.Severity.ERROR,IfullfillTextConstant.EMPTY_ROW_SELECTION_MSG);
                ApexPages.addMessage(msg);
                Page = null;
           }
        
          // check if the user has selected FI which is in outed,Cancelled or Live status
                  
          fiName = checkStatus();
          if(fiName != null)
          {
                String temp  = 'Cannot change the owner of '+ fiName +' please deselect the row.';
                ApexPages.Message msg = new ApexPages.Message(ApexPages.Severity.ERROR,temp );
                ApexPages.addMessage(msg);
                Page = null;
          }      
          return Page ;
    }
    /*
     *  Validate user has not selected the FI in outed, canceled,Live Status
     *
     **/
    private String checkStatus()
    {
         errorFlag = false; 
         String fiName = null;
         Set<ID> tempID  = selectedMap.keySet();
         DateTime todayDate  = System.now();
         Boolean flag = false;
         for (Id fiID : tempId)
         {
            Fullfilment_Item__C item  = selectedMap.get(fiID);
            flag = false;
            if(item != null)
           { 
                    // Chech if user is trying to update the record which has Future Cancellation date
                    if(  item.Future_Cancellation__c!= null &&
                         IfullfillTextConstant.FI_CANCELLATION_TRANS_TYPE.equalsIgnoreCase(item.Transaction_Type__c) &&
                         todayDate < DateTime.valueOf(item.Future_Cancellation__c).addDays(1))
                    {
                        flag = true;
                    }
                     // Check if FI is in outed/cancel/live Status
                     if(item.Status__c != null && (item.Status__c.equalsIgnoreCase(IfullfillTextConstant.FI_WORKFLOW_OUTED_STATUS) || 
                                                   item.Status__c.equalsIgnoreCase(IfullfillTextConstant.FI_WORKFLOW_CANCELED_STATUS ) || 
                                                   item.Status__c.equalsIgnoreCase(IfullfillTextConstant.FI_WORKFLOW_LIVE_STATUS )) || flag )
                     {
                         errorFlag  = true;
                         if(fiName== null)
                         {
                             fiName= item.name;
                         }
                         else
                         {
                              fiName=  fiName+ ','+item.name;
                         }
                     }          
                 }
          }
          return fiName;
    }
    /* 
     *   Update the FI record Owner
     *
     **/
    public Pagereference  saveOwner()
    {
         boolean success = true;
         populatedSelectedRec();
         List<Fullfilment_Item__C> changeOwnerList = new List<Fullfilment_Item__C>();
         Pagereference Page = new Pagereference(IfulfillVFPagesName.FI_ADV_SEARCH_PAGE );   
         Set<ID> tempID  = selectedMap.keySet();
          
         // Check user has selected the FI owner name 
          
         if( !selectFormMyQueue && (FulfillItem.ownerid == null))
         {
               ApexPages.Message msg = new ApexPages.Message(ApexPages.Severity.ERROR, IfullfillTextConstant.OWNER_FIELD_NOT_NULL_MSG);
               ApexPages.addMessage(msg);    
               return null;
         }
         // check the user  has selected "Select My Queue" check box
         
         else if(selectFormMyQueue &&  (changeOwnerQueue == null || changeOwnerQueue == '' ))
         {                 
               ApexPages.Message msg = new ApexPages.Message(ApexPages.Severity.ERROR, IfullfillTextConstant.QUEUE_FIELD_NOT_NULL_MSG);
               ApexPages.addMessage(msg);    
               return null;
         }
         
        
         for (Id fiID : tempId)
         {
            Fullfilment_Item__C item  = selectedMap.get(fiID);
            if(item != null)
            {        // Change the FI owner field
                     if(!selectFormMyQueue )
                     {
                         item.ownerId = FulfillItem.ownerid;
                         changeOwnerList.add(item);
                     }
                     else if(selectFormMyQueue  && changeOwnerQueue !=null)
                     {
                         item.ownerId =changeOwnerQueue;
                         changeOwnerList.add(item);
                     }
            }
            
         }
         
         FulfillItem.ownerid = null;
         if(changeOwnerList.size() > 0)
         {    
             try
             {  
                 // Change the owner and update the FI 
                 update changeOwnerList;
             }
             catch(Exception e )
             {       
                 Page = null;
                 success  = false;
                 IfullfillTextConstant.parseExceptionMsg(e,'ItemSearchController','saveOwner');
             }
         }
         if(success )
         {
             selectFormMyQueue = false;
             doSearch();
         }
         return Page;
    }
    /* 
     *   Move to change owner page   
     *
     **/
    public Pagereference cancelOwnerChange()
    {
         Pagereference Page = new Pagereference(IfulfillVFPagesName.FI_ADV_SEARCH_PAGE ); 
          FulfillItem.ownerid = null;
          selectFormMyQueue = false;   
          return Page ;
    }
    /* 
     *  Returns Filter View List option
     *
     **/
    public List<selectOption> getFilterViewItem()
    {
    
          List<selectOption> options = new List<selectOption>(); 
          options.add(new selectOption(IfullfillTextConstant.MY_QUEUE_ITEMS_TXT, IfullfillTextConstant.MY_QUEUE_ITEMS_TXT)); 
          options.add(new selectOption(IfullfillTextConstant.ALL_ITEMS_TXT, IfullfillTextConstant.ALL_ITEMS_TXT )); 
          options.add(new selectOption(IfullfillTextConstant.MY_ITEMS_TXT, IfullfillTextConstant.MY_ITEMS_TXT )); 
          return  options;
    }
    
    /* 
     *  Returns the Region of FI 
     *
     **/
    public List<SelectOption> getRegion()
    {
        List<selectOption> options = new List<selectOption>(); 
        
        options.add(new selectOption('', IfullfillTextConstant.PICKLIST_NONE_TXT)); 
        Schema.DescribeFieldResult rest =   Fullfilment_Item__c.Region__c.getDescribe();
        for(Schema.PickListEntry FinalsPickVal : rest.getPicklistValues())
        {
            options.add(new SelectOption(FinalsPickVal.getValue(),FinalsPickVal.getLabel()));
        }
        return options;
    }  
    /* 
     *  Returns the Transaction type  of FI 
     *
     **/
    public List<SelectOption> getTransactionType()
    {
        List<selectOption> options = new List<selectOption>(); 
        
        options.add(new selectOption('', IfullfillTextConstant.PICKLIST_NONE_TXT)); 
        Schema.DescribeFieldResult rest =   Fullfilment_Item__c.Transaction_Type__c.getDescribe();
        for(Schema.PickListEntry FinalsPickVal : rest.getPicklistValues())
        {
            options.add(new SelectOption(FinalsPickVal.getValue(),FinalsPickVal.getLabel()));
        }
        return options;
    }
    
    /** 
     *  To keep track of the selected FI.  
     *
     */
   private void populatedSelectedRec()   
   {
         Set<ID> selecteRowId = selectedMap.keySet();
         Set<ID> displayRecID = new Set<ID>(); 
        
         for(FullfilmentWrapper fiWrapper1 : displayedWrapperList )
         { 
            displayRecID.add(fiWrapper1.item.id);
         }
         selecteRowId.removeAll(displayRecID);
         for(FullfilmentWrapper fiWrapper : displayedWrapperList )
         { 
              if(fiWrapper.selectBox)
              {
                   selectedMap.put(fiWrapper.item.ID , fiWrapper.item); 
              }
         }
    }
    
    /**
     * implement the Column Sorting 
     */
    
    public void doSort()
    {
        String order = 'asc'; 
        populatedSelectedRec();
        
        /*This checks to see if the same header was click two times in a row, if so 
        it switches the order.*/
        if(previousSortField == sortField)
        {
            order = 'desc';
            previousSortField = null;
        }
        else
        {
            previousSortField = sortField;
        }
       //To sort the table we simply need to use this one line, nice!
       sortList(fullFilmentItemList,sortField,order);
    }
    
     public static void sortList(List<sObject> items, String sortField, String order){
        /*I must give credit where it is due as the sorting algorithm I am using is the 
        one supplied by Andrew Waite here: http://blog.sforce.com/sforce/2008/09/sorting-collect.html */
        
        Boolean isSortFieldReference = false;
        Map<Id,String> referenceName;
         
        /*Determine the type of the field that needs to be sorted, if it is a 
        reference we will want sort by the name of the related object, not the 
        ID itself*/
        if(items[0].getSObjectType().getDescribe().fields.getMap().get(sortField).getDescribe().getType().Name() == 'REFERENCE'){
            isSortFieldReference = true;
            referenceName = new Map<Id,String>();
            
            /*Determine the type of this object and populate the Id to Name map*/
            Set<Id> referenceIds = new Set<Id>();
            for(sObject s : items){
               referenceIds.add((Id)s.get(sortField));
            }
            
            // DevAngel - EDIT - Because you may not have a value for the reference field in the first record
            // in the table you are sorting, this approach will fail on the substring method.  Below is
            // is a more reliable method using describe calls
            /*
            String objectID = (String)items[0].get(sortField);
            String prefix = objectID.substring(0,3);
            String objectType;
            Map<String, Schema.SObjectType> gd = Schema.getGlobalDescribe();
            for(Schema.SObjectType s : gd.values()){
                if(prefix == s.getDescribe().getKeyPrefix()){
                    objectType = s.getDescribe().Name;
                }
            }
            */

            // DevAngel - EDIT - New approach...
            List<Schema.Sobjecttype> objType = items[0].getSObjectType().getDescribe().fields.getMap().get(sortField).getDescribe().getReferenceTo();
            String objectType = objType[0].getDescribe().getName();

            //Query the related objects for the name and populate the Id -> Name map
            String queryString = 'select Id, Name from ' + objectType + ' where ID IN :referenceIDs';
            for(sObject s : Database.query(queryString )){
                // DevAngel - EDIT - if the reference field is null then we will not have a result, so we need to "create one"
                if (s.get('Name') == null) {
                    referenceName.put((Id)s.get('Id'), 'n/a');
                } else {
                    referenceName.put((Id)s.get('Id'),(String)s.get('Name'));
                }
            }
        }
                
        /*Declare a list that will contain the sorted results. I think this is one of the 
        coolest parts of this method as the system will not let you declare a list of 
        sObjects (List<sObject> objects = new List<sObjects>();) but using a 
        wrapper class you can bypass this system limitation to create this type of list */
        List<cObject> resultList = new List<cObject>();
    
        //Create a map that can be used for sorting 
        Map<object, List<cObject>> objectMap = new Map<object, List<cObject>>();
        
        for(sObject ob : items){
            if(isSortFieldReference == false){
                if(objectMap.get(ob.get(sortField)) == null){ 
                    objectMap.put(ob.get(sortField), new List<cObject>()); 
                }
                cObject o = new cObject(ob);
                objectMap.get(ob.get(sortField)).add(o);
            }else{
                if(objectMap.get(referenceName.get((Id)ob.get(sortField))) == null){ 
                    objectMap.put(referenceName.get((Id)ob.get(sortField)), new List<cObject>()); 
                }
                cObject o = new cObject(ob);
                objectMap.get(referenceName.get((Id)ob.get(sortField))).add(o);
            }
        }
        
        //Sort the keys
        List<object> keys = new List<object>(objectMap.keySet());
        keys.sort();
        
        for(object key : keys){ 
            resultList.addAll(objectMap.get(key)); 
        }
        
        //Apply the sorted values to the source list
        items.clear();
        if(order.toLowerCase() == 'asc'){
            for(cObject ob : resultList){
                items.add(ob.obj);  
            }
        }else if(order.toLowerCase() == 'desc'){
            for(integer i = resultList.size()-1; i >= 0; i--){
                items.add(resultList[i].obj);   
            }
        }
    }
    
     /*
      *  Wrapper class used for sorting
      *
      **/
    public class cObject{
        sObject obj {get; set;}
        
        public cObject(sObject obj){
            this.obj = obj; 
        }
    }
    /*
     * Set the Max id.
     */
    private void setMaxID()
    {
         maxId = fullFilmentItemList.size() >0 ? fullFilmentItemList.get(fullFilmentItemList.size()-1).name : ''; 
    }
    
  
    /*
     *   Render the Change owner Button 
     *
     **/
     
     private Boolean initializeChangeOwner()
     {
            Boolean changeOwner = false;
            List <Profile> profileList  = [select name from profile  where id  = :userinfo.getProfileId()];
            List<PermissionSetAssignment> permissionSetAssignList  = [SELECT Id, AssigneeId FROM PermissionSetAssignment WHERE PermissionSetId in (SELECT Id FROM PermissionSet where name = :IfullfillTextConstant.IFULFILL_IR_VERIFY_MGR_PERMISSION_SET_NAME)and AssigneeId = :userinfo.getUserId()];
            
            if(permissionSetAssignList.size() > 0)
            {
                return true;
            }          
            
            // Check if loged in user is a part of IOG - Support - Reporting * or sys admin or ifulfill workflow admin profile.

             if( profileList.get(0).name.startsWith(IfullfillTextConstant.IOG_SUPPORT_REPORTING_PROFILE_STARTS_WITH) || 
                 profileList.get(0).name.startsWith(IfullfillTextConstant.SYSTEM_ADMIN_PROFILE_STARTS_WITH) || 
                 IfullfillTextConstant.IFULFILL_WORKFLOW_ADMIN_PROFILE_NAME.equalsIgnoreCase(profileList.get(0).name))
             {
                    changeOwner = true;
             }
             return changeOwner;            
     }   
      
     /*
      *  Return the MAX no of records a query can return.
      *
      **/
      
     public Integer getLimitQueryRows()
     {
         return Limits.getLimitQueryRows();
     }
     /**
      *   picklist value for Escalated List box. 
      *  
      */
     public List<SelectOption> getEscalated()
     {
        List<selectOption> options = new List<selectOption>();
        options.add(new selectOption('', IfullfillTextConstant.ALL_TXT)); 
        options.add(new selectOption(IfullfillTextConstant.ESCALATED_TXT, IfullfillTextConstant.ESCALATED_TXT)); 
        options.add(new selectOption(IfullfillTextConstant.NON_ESCALATED_TXT ,IfullfillTextConstant.NON_ESCALATED_TXT)); 
        return options;
     }
}